STM32与MQTT(一)STM32+ESP8266连接TCP服务器
0. 前言1. 开发前准备1.1 准备工作1.2 说明
2. 开发过程2.1 USART1与USART2串口使用2.1.1 两个串口使用上的区别2.1.2 工程配置2.1.3 修改 "usart.h"2.1.4 修改 "usart.c"2.1.5 修改 "stm32f1xx_it.c"2.1.6 设置监听2.1.7 测试代码
2.2 连接STM32与ESP82662.2.1 熟悉AT指令2.2.2 串口驱动ESP8266连接电脑TCP服务器2.2.3 STM32驱动ESP8266连接电脑TCP服务器
3. 结束
0. 前言
本系列不讲MQTT协议具体的原理,只说怎么使用STM32+ESP8266在裸机状态下使用HAL库连接华为云MQTT服务器
1. 开发前准备
1.1 准备工作
STM32F103C8T6核心板正点原子ATK-ESP-01模块(也可以使用其他ESP8266模块)开发环境:STM32CubeIDE串口调试助手参考作者 张竞豪 的文章,写的真的很好
1.2 说明
使用资源说明
使用资源功能USART1DBG信息打印USART2连接ESP8266模块进行配置与网络通信DMA1_Channel6USART2_Rx的DMA用作与接收数据PB15ESP8266模块复位引脚PC13板载LED灯
正点原子ATK-ESP-01模块使用请下载资料,就算使用其他的ESP8266模块也可使用正点原子的资料,主要参考资料中对于ESP8266的AT指令集的说明。使用STM32CubeIDE开发,集成环境,个人觉得在STM32开发上比MDK环境好用使用野火的fireTool,网络调试,串口调试一应俱全虽然我没有私信联系这位作者,但是我很感谢他,基本上是跟着他文章做下来的
2. 开发过程
2.1 USART1与USART2串口使用
2.1.1 两个串口使用上的区别
请耐心看完以下内容 使用USART1时,考虑到在设计中只用作DBG信息打印,因此对其接收没有要求,甚至不需要接收,在这里我没有用到USART1的接收功能 使用USART2时,首先要搞清楚,USART2是如何通过ESP8266连接网络,并进行通信的。类比HC-05等的蓝牙模块,这类模块通过串口线连接到串口上,配置并连接完成后,对下层透明,下层不需要关心协议如何实现,只对其连接的串口发送信息,而将信息加上头部、解包或无线传输等功能完全由该芯片(模块)实现。所以类比HC-05等蓝牙模块,我们对ESP8266模块要做的事情非常简单:正确配置,连接网络,使能发送。 由于USART2需要发送与接收数据,显然,发送数据的长度是本地可控的,简单使用HAL库函数即可完成,但是接收数据的长度是不可控的,其完全由配置过程中ESP8266返回的数据和配置完成后ESP8266接收到的数据长度指定,即接收到的数据是不定长的,为了实现不定长实时数据接收,在这里我们使用DMA+中断的方法(参考文章找不到了,但是能搜到的方法大致相同,我也会贴出我用到的方法)。
2.1.2 工程配置
使用资源一览,时钟树使用外部晶振,直接拉满就可以 DMA1_Channel6 配置直接使用默认的就可以 让STM32CubeIDE内置的CubeMX在生成代码时按照库的方式来生成 扩大栈堆 ![配置图4](https://img-blog.csdnimg.cn/1760a174452543f091b00772ab1c1d79.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbjExMTF5aQ==,size_16,color_FFFFFF,t_70)
2.1.3 修改 “usart.h”
打开生成后的工程中usart.h 在usart.h中加入需要用到的变量
/* 对照注释提示插入代码,不在注释包括出来的
* 区域内的代码在重新生成代码时会被清除
*/
/* USER CODE BEGIN Private defines */
// 用户代码开始
#define USART1_MAX_SENDLEN 1024
#define USART1_MAX_RECVLEN 1024
#define USART2_MAX_SENDLEN 1024
#define USART2_MAX_RECVLEN 1024
// 用户代码结束
/* USER CODE END Private defines */
void MX_USART1_UART_Init(void); // CubeMX生成的代码
void MX_USART2_UART_Init(void); // CubeMX生成的代码
/* USER CODE BEGIN Prototypes */
// 用户代码开始
extern uint8_t USART1_TxBUF[USART1_MAX_SENDLEN];// usart1 发送数据缓存区
extern uint8_t USART1_RxBUF[USART1_MAX_RECVLEN];// usart1 接收数据缓存区
extern uint8_t USART2_TxBUF[USART2_MAX_SENDLEN];// usart2 发送数据缓存区
extern uint8_t USART2_RxBUF[USART2_MAX_RECVLEN];// usart2 接收数据缓存区
extern volatile uint8_t USART2_RxLen;// usart2 接收数据长度
extern volatile uint8_t USART2_RecvEndFlag;// usart2 接收数据完成标志位
// 对usart1发送数据
void u1_printf(char *fmt, ...);
// 我不喜欢将对usart2发送数据也命名为printf,因为实际上并没有对我print
void u2_transmit(char *fmt, ...);
// 用户代码结束
/* USER CODE END Prototypes */
2.1.4 修改 “usart.c”
在 MX_USART2_UART_Init(void) 函数中添加以下代码,开启IDLE中断,并使能DMA接收 在最后添加第2步中声明的两个函数的函数体
void MX_USART2_UART_Init(void) {
//......
/* USER CODE BEGIN USART2_Init 2 */
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart2, USART2_RxBUF, USART2_MAX_RECVLEN);
/* USER CODE END USART2_Init 2 */
//......
}
/**********************分割线**********************/
/* USER CODE BEGIN 1 */
// 用户代码开始
void u1_printf(char *fmt, ...) {
uint16_t i;
va_list ap;
va_start(ap, fmt);
vsprintf((char*) USART1_TxBUF, fmt, ap);
va_end(ap);
i = strlen((const char*) USART1_TxBUF);
HAL_UART_Transmit(&huart1, USART1_TxBUF, i, 100);
memset(USART1_TxBUF, 0, USART1_MAX_SENDLEN);
}
void u2_transmit(char *fmt, ...) {
uint16_t i, j;
va_list ap;
va_start(ap, fmt);
vsprintf((char*) USART2_TxBUF, fmt, ap);
va_end(ap);
// 排除掉发送信息中所有的'\00'使有效信息可以发送
// 但是仍要考虑到,MQTT报文等内容中可能含有'\00'
// 这个时候就需要直接使用HAL_UART_Transmit()函数发送
// 而放弃使用u2_transmit()
for (i = 0; i
for (; j
/* USER CODE BEGIN USART2_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag = __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE);
if ((tmp_flag != RESET)) {
__HAL_UART_CLEAR_IDLEFLAG(&huart2);
temp = huart2.Instance->SR;
temp = huart2.Instance->DR;
HAL_UART_DMAStop(&huart2);
temp = hdma_usart2_rx.Instance->CNDTR;
USART2_RxLen = USART2_MAX_RECVLEN - temp;
USART2_RecvEndFlag = 1;
}
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
2.1.6 设置监听
完成上述步骤后,如果需要获取USART2接收到的数据只需要在需要获取数据的位置监听 USART2_RecvEndFlag 的值,当其为1时,读取USART2_RxBUF的内容即可,示例:
/* 在timeout时间内进行监听,
* 如果监听到USART2_RecvEndFlag为1则对数据进行处理
*/
while (timeout--) {
// u1_printf("%d ", timeout);
// finish dma receive
if (USART2_RecvEndFlag == 1) {
check = esp8266_CheckRespond(ack);
if (check == _MATCHOK) {
u1_printf("(DBG:) Command closed loop completed\r\n");
}
USART2_RxLen = 0;
USART2_RecvEndFlag = 0;
HAL_UART_Receive_DMA(&huart2, USART2_RxBUF, USART2_MAX_RECVLEN);
break;
}
HAL_Delay(1);
}
2.1.7 测试代码
不做展开,请自己测试一下,如果不成功,请搜索相关内容再次尝试,只要usart2能够实现不定长数据接收,就可开始下一步
2.2 连接STM32与ESP8266
2.2.1 熟悉AT指令
请耐心看完以下内容 如果你已经下载了正点原子的资料,那么可以打开6,ESP8266相关资料文件夹,查阅ESP8266_AT指令集V2.1.0了解ESP8266的AT指令集,在实际连接前,可以先使用CH340x、CP2102等串口模块通过串口调试助手将ESP8266模块连接到网络,熟悉这个过程后,只需要使用STM32的USART2向ESP8266模块发送在串口助手中发送过的指令,就可以使用STM32驱动ESP8266连接网络 那么先来了解一下本次需要用到的AT指令,均来自ESP8266_AT指令集V2.1.0
AT指令作用+++请参照说明文档AT\r\nAT测试指令,返回OKATEx\r\nx:0—关闭回显,1—打开回显AT+CWMODE_CUR=x\r\n设置模块工作模式,不保存到Flash,x:0—AP,1—STA,2—AP+STAAT+CWAUTOCONN=x\r\n设置自动连接,x:0—关闭,1—开启AT+CWJAP_CUR=“ssid”,“pswd”\r\n连接AP网络,不保存到Flash,ssid—网络名称,pswd—密码AT+CWJAP_CUR?\r\n查询网络信息,需要连接到网络AT+CIPSTA_CUR?\r\n查询IP信息,需要连接到网络AT+CWDHCP_CUR=x,y\r\n请参照说明文档AT+CIPMUX=x\r\n多连接模式设置,x:0—关闭,1—开启AT+CIPMODE=x\r\n传输模式设置,x:0—普通模式,1—透传模式AT+CIPSTART=“mode”,“IpServer”,ServerPort\r\n连接到服务器,具体请参照说明文档,mode指示服务器类型,IpServer指示服务器地址,ServerPort指示服务器端口AT+CIPSEND\r\n发送数据
其他AT指令请查阅文档,将以上步骤按照设定参数并需要执行一次后,向ESP8266发送数据,TCP服务端即可收到数据。
2.2.2 串口驱动ESP8266连接电脑TCP服务器
接收数据测试,以连接WIFI上网的Windows电脑为例:
在命令行中使用ipconfig查找到本机的ip地址 在串口调试助手中设置 端口使用默认端口即可,注意这两个对应上述指令中的AT+CIPSTART=“mode”,“IpServer”,“ServerPort”,将mode设置为TCP,因为连接的是TCP服务器使用USB转串口模块连接电脑与ESP8266模块,在串口中向ESP8266模块发送下图所示指令,得到返回结果,注意在发送服务器信息时,端口号不加引号,最后进行发送信息测试 发送测试信息
2.2.3 STM32驱动ESP8266连接电脑TCP服务器
创建 “esp8266.h” 和 “esp8266.c” 文件检查AT指令返回的数据 使用函数strstr(str1, str2) 具体原理不赘述,该函数如果查找成功则返回值不为NULL。使用此方法可以检查发送AT指令后得到的返回结果是否为预期,由此来判断AT指令是否成功发送以及是否起作用
// WIFI_StateTypeDef 是我自己定义的一个表示ESP8266状态的enum类型
// str 为期望的返回,如期望返回 "OK",则str应设置为 "OK"
WIFI_StateTypeDef esp8266_CheckRespond(uint8_t *str) {
u1_printf("(DBG:) usart2 recv:\r\n%s\r\n", USART2_RxBUF);
if (strstr((const char*) USART2_RxBUF, (const char*) str) != NULL) {
u1_printf("(DBG:) Match succeed\r\n");
memset(USART2_RxBUF, 0, USART2_MAX_RECVLEN);
return _MATCHOK;
}
memset(USART2_RxBUF, 0, USART2_MAX_RECVLEN);
return _MATCHERROR;
}
发送AT指令并检查指令闭环
/**
* @param cmd: cmd to be send
* @param ack: correct ack to be checked
* @param waitms: wait time ms
* @param newline: transmit a new line or not
*/
WIFI_StateTypeDef esp8266_TransmitCmd(uint8_t *cmd, uint8_t *ack,
uint32_t waitms, uint8_t newline) {
int timeout = waitms;
uint8_t check = 0;
memset(USART2_RxBUF, 0, USART2_MAX_RECVLEN);
u1_printf("\r\n(DBG:) Try to send cmd: %s\r\n", cmd);
if (newline == 0)
u2_transmit("%s", cmd); // transmit cmd to usart2
else
u2_transmit("%s\r\n", cmd); // transmit cmd to usart2
u1_printf("(DBG:) Waiting reply\r\n");
while (timeout--) {
// u1_printf("%d ", timeout);
// finish dma receive
if (USART2_RecvEndFlag == 1) {
check = esp8266_CheckRespond(ack);
if (check == _MATCHOK) {
u1_printf("(DBG:) Command closed loop completed\r\n");
}
USART2_RxLen = 0;
USART2_RecvEndFlag = 0;
HAL_UART_Receive_DMA(&huart2, USART2_RxBUF, USART2_MAX_RECVLEN);
break;
}
HAL_Delay(1);
}
if (check == _MATCHERROR) {
u1_printf("\r\n(DBG:) Cmd match failed\r\n");
return check;
}
if (timeout
uint8_t retry_count = 0;
/* Other steps */
/**************************分割线**************************/
/* Close echo */
u1_printf("(DBG:) Trying to close echo\r\n");
wifi_config_step++;
while (esp8266_TransmitCmd((uint8_t*) "ATE0", OK_ACK, 500, WITH_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Close echo failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(100);
retry_count = 0; // reset retry count
/**************************分割线**************************/
/* Other steps */
}
测试使用STM32驱动ESP8266连接电脑TCP服务器 在github仓库中找到 “esp8266.c” 和 “net_conf.h” 两个文件,对 “net_conf.h” 中的网络相关属性做配置,或使用其他的方法使函数可以获取TCP服务器的地址和端口,下面是 “net_conf.h” 的内容
#ifndef __NET_CONF_H
#define __NET_CONF_H
// Please modify those macro definitions to meet needs
#define WIFI_TAR 1
#if WIFI_TAR == 0
#define AP_SSID (const char*)"YOUR OWN WIFI SSID"
#define AP_PSWD (const char*)"YOUR OWN WIFI PSWD"
#elif WIFI_TAR == 1
#define AP_SSID (const char*)"YOUR OWN PC AP SSID"
#define AP_PSWD (const char*)"YOUR OWN PC AP PSWD"
#endif
#define CONNECT_MODE 0
#if CONNECT_MODE == 0
#define IpServer "YOUR OWN MQTT SERVER ADDRESS"
#define ServerPort "YOUR OWN MQTT SERVER PORT"
#elif CONNECT_MODE == 1
#define IpServer "YOUR OWN PC TCP SERVER ADDRESS"
#define ServerPort "YOUR OWN PC TCP SERVER PORT"
#endif
#define MQTT_DEVICE_ID (uint8_t*)"YOUR OWN MQTT DEVICE ID"
#define MQTT_SECRET (uint8_t*)"YOUR OWN MQTT DEVICE SECRET CODE"
#define MQTT_CLIENTID "YOUR OWN MQTT DEVICE CLIENTID"
#define MQTT_USERNAME "YOUR OWN MQTT DEVICE USERNAME"
#define MQTT_PASSWORD "YOUR OWN MQTT DEVICE PASSWORD"
#endif
上面所说的工程中只需要esp8266相关文件即可使STM32驱动ESP8266连接TCP服务器,请务必读多读几遍代码,esp8266.c 代码如下,实际上就是使用之前说的两个函数复现使用串口助手发送AT指令的过程,并加入确认部分,请先运行以下代码通过将测试信息发送给电脑TCP服务器成功后,再进行后续内容
#include "esp8266.h"
static WIFI_StateTypeDef wifi_state = _OFFLINE;
static WIFI_StateTypeDef trans_state = _UNKNOWN_STATE;
static uint8_t wifi_config_step = 0;
WIFI_StateTypeDef esp8266_CheckRespond(uint8_t *str) {
u1_printf("(DBG:) usart2 recv:\r\n%s\r\n", USART2_RxBUF);
if (strstr((const char*) USART2_RxBUF, (const char*) str) != NULL) {
u1_printf("(DBG:) Match succeed\r\n");
memset(USART2_RxBUF, 0, USART2_MAX_RECVLEN);
return _MATCHOK;
}
memset(USART2_RxBUF, 0, USART2_MAX_RECVLEN);
return _MATCHERROR;
}
WIFI_StateTypeDef esp8266_TransmitCmd(uint8_t *cmd, uint8_t *ack,
uint32_t waitms, uint8_t newline) {
int timeout = waitms;
uint8_t check = 0;
memset(USART2_RxBUF, 0, USART2_MAX_RECVLEN);
u1_printf("\r\n(DBG:) Try to send cmd: %s\r\n", cmd);
if (newline == 0)
u2_transmit("%s", cmd); // transmit cmd to usart2
else
u2_transmit("%s\r\n", cmd); // transmit cmd to usart2
u1_printf("(DBG:) Waiting reply\r\n");
while (timeout--) {
// u1_printf("%d ", timeout);
// finish dma receive
if (USART2_RecvEndFlag == 1) {
check = esp8266_CheckRespond(ack);
if (check == _MATCHOK) {
u1_printf("(DBG:) Command closed loop completed\r\n");
}
USART2_RxLen = 0;
USART2_RecvEndFlag = 0;
HAL_UART_Receive_DMA(&huart2, USART2_RxBUF, USART2_MAX_RECVLEN);
break;
}
HAL_Delay(1);
}
if (check == _MATCHERROR) {
u1_printf("\r\n(DBG:) Cmd match failed\r\n");
return check;
}
if (timeout
int timeout = waitms;
WIFI_RST_Enable();
HAL_Delay(500);
WIFI_RST_Disable();
while (timeout--) {
if (USART2_RecvEndFlag == 1) {
u1_printf("(DBG:) Hardware Reset OK!\r\n");
HAL_Delay(100);
USART2_RxLen = 0;
USART2_RecvEndFlag = 0;
HAL_UART_Receive_DMA(&huart2, USART2_RxBUF, USART2_MAX_RECVLEN);
return _SUCCEED;
}
HAL_Delay(1);
}
if (timeout
uint16_t cmd_len = strlen(AP_SSID) + strlen(AP_PSWD) + 30;
uint8_t *cmd = (uint8_t*) malloc(cmd_len * sizeof(uint8_t));
memset(cmd, 0, cmd_len);
sprintf((char*) cmd, "AT+CWJAP_CUR=\"%s\",\"%s\"", AP_SSID, AP_PSWD);
if (esp8266_TransmitCmd(cmd, (uint8_t*) "WIFI CONNECTED",
3 * ESP8266_MAX_TIMEOUT, WITH_NEWLINE) == _SUCCEED)
wifi_state = _ONLINE;
else
wifi_state = _OFFLINE;
return wifi_state;
}
WIFI_StateTypeDef esp8266_ConnectServer() {
uint16_t cmd_len = strlen(IpServer) + strlen(ServerPort) + 30;
uint8_t *cmd = (uint8_t*) malloc(cmd_len * sizeof(uint8_t));
memset(cmd, 0, cmd_len);
sprintf((char*) cmd, "AT+CIPSTART=\"TCP\",\"%s\",%s", IpServer, ServerPort);
if (esp8266_TransmitCmd(cmd, (uint8_t*) "CONNECT", 3 * ESP8266_MAX_TIMEOUT,
WITH_NEWLINE) == _SUCCEED)
wifi_state = _CONNECTED;
else
wifi_state = _DISCONNECTED;
return wifi_state;
}
WIFI_StateTypeDef esp8266_SetUpTCPConnection() {
uint8_t retry_count = 0;
/* Reset esp8266 */
u1_printf("(DBG:) Trying to reset esp8266\r\n");
wifi_config_step++;
while (esp8266_HardwareReset(500) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Reset failed\r\n");
retry_count = 0;
trans_state = _UNKNOWN_STATE;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(2000); // wait 2 seconds
retry_count = 0; // reset retry count
/* Disable transparent transmission */
u1_printf("(DBG:) Trying to close transparent transmission\r\n");
wifi_config_step++;
while (esp8266_TransmitCmd(TRANS_QUIT_CMD, TRANS_QUIT_CMD,
ESP8266_MAX_TIMEOUT,
WITHOUT_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1500);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Close transparent transmission failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
trans_state = _TRANS_DISABLE;
HAL_Delay(1500);
retry_count = 0; // reset retry count
/* Close echo */
u1_printf("(DBG:) Trying to close echo\r\n");
wifi_config_step++;
while (esp8266_TransmitCmd((uint8_t*) "ATE0", OK_ACK, 500, WITH_NEWLINE)
!= _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Close echo failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(100);
retry_count = 0; // reset retry count
/* Set wifi mode 0:AP 1:STA 2:AP+STA */
u1_printf("(DBG:) Trying to set Wifi mode\r\n");
wifi_config_step++;
while (esp8266_TransmitCmd((uint8_t*) "AT+CWMODE_CUR=1", OK_ACK, 500,
WITH_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Set Wifi mode failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(100);
retry_count = 0; // reset retry count
/* Disable auto connect */
u1_printf("(DBG:) Trying to close auto connect\r\n");
wifi_config_step++;
while (esp8266_TransmitCmd((uint8_t*) "AT+CWAUTOCONN=0", OK_ACK, 500,
WITH_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Close auto connect failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(100);
retry_count = 0; // reset retry count
/* Connect to AP(Wifi) */
u1_printf("(DBG:) Trying to connect to AP\r\n");
wifi_config_step++;
while (esp8266_ConnectAP() != _ONLINE) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Connect to AP failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(1000);
retry_count = 0; // reset retry count
/* Try to get AP info */
if (wifi_state == _ONLINE) {
while (esp8266_TransmitCmd((uint8_t*) "AT+CWJAP_CUR?", OK_ACK,
ESP8266_MAX_TIMEOUT, WITH_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME / 2) {
u1_printf("(DBG:) Get AP msg failed\r\n");
u1_printf(
"(DBG:) Connect server process will not be terminated");
retry_count = 0;
wifi_config_step--;
break;
}
}
}
HAL_Delay(1000);
retry_count = 0; // reset retry count
/* Try to get IP info */
if (wifi_state == _ONLINE) {
while (esp8266_TransmitCmd((uint8_t*) " AT+CIPSTA_CUR?", OK_ACK,
ESP8266_MAX_TIMEOUT, WITH_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME / 2) {
u1_printf("(DBG:) Get IP info failed\r\n");
u1_printf(
"(DBG:) Connect server process will not be terminated");
retry_count = 0;
wifi_config_step--;
break;
}
}
}
HAL_Delay(1000);
retry_count = 0; // reset retry count
/* Set DHCP */
u1_printf("(DBG:) Trying to set DHCP mode\r\n");
wifi_config_step++;
while (esp8266_TransmitCmd((uint8_t*) "AT+CWDHCP_CUR=1,1", OK_ACK, 1000,
WITH_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Set DHCP model failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(1000);
retry_count = 0;
/* Set single connection */
u1_printf("(DBG:) Trying to set single connection\r\n");
wifi_config_step++;
while (esp8266_TransmitCmd((uint8_t*) "AT+CIPMUX=0", OK_ACK, 1000,
WITH_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Set single connection model failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(1000);
retry_count = 0;
/* Set transparent transmission */
u1_printf("(DBG:) Trying to set transparent transmission mode\r\n");
wifi_config_step++;
while (esp8266_TransmitCmd((uint8_t*) "AT+CIPMODE=1", OK_ACK, 1000,
WITH_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Set transparent transmission mode failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(1000);
retry_count = 0;
/* Connect to TCP server */
u1_printf("(DBG:) Trying to connect TCP server\r\n");
wifi_config_step++;
while (esp8266_ConnectServer() != _CONNECTED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Connect TCP server failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
HAL_Delay(1000);
retry_count = 0;
/* enable data send(transparent transmission) */
u1_printf("(DBG:) Trying to enable data send\r\n");
wifi_config_step++;
while (esp8266_TransmitCmd((uint8_t*) "AT+CIPSEND", OK_ACK, 1000,
WITH_NEWLINE) != _SUCCEED) {
retry_count++;
HAL_Delay(1000);
if (retry_count > ESP8266_MAX_RETRY_TIME) {
u1_printf("(DBG:) Set transparent transmission mode failed\r\n");
retry_count = 0;
wifi_config_step--;
return _FAILED;
}
}
trans_state = _TRANS_ENBALE;
HAL_Delay(1000);
retry_count = 0;
/* send test msg */
// u1_printf("Test msg is sending to TCP Server\r\n");
// u2_transmit("This msg means TCP connection has been set up\r\n");
// u1_printf("Test msg has been send to TCP Server\r\n");
return _SUCCEED;
}
3. 结束
参考代码,完成上述过程后,STM32可以成功驱动ESP8266连接TCP服务器,连接不同的TCP服务器只需要修改配置中的服务器地址和服务器端口即可。
祝各位身体健康
|